/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "nfa_base.h"
#include "hci_cmd.h"
#include "hci_defs.h"
#include "hci_session.h"
#include "nfc_log_api.h"
#include "ee_int.h"
#include "nci_nfcee.h"
#include "nfc_osi_api.h"
#include "nci_feature.h"

/*
 * @brief  管理HCI session缓存
 */

#if IS_FEATURE_ON(NCI_FEATURE_HCI)

#define MAX_DYN_PIPE (10)
#define MAX_HOST_NUM (5)

typedef struct {
    uint8_t pipe_id;
    uint8_t local_gate;
    uint8_t dest_host;
    uint8_t dest_gate;
    bool is_opened;
} tHCI_PIPE_INFO;

typedef struct {
    uint8_t session_id[HCI_REGISTRY_SESSION_ID_LEN];
    tHCI_PIPE_INFO dyn_pipes[MAX_DYN_PIPE];
} tHCI_SESSION_INFO;

static tNCI_STATUS hci_get_session_id(uint8_t *session_id);
static tNCI_STATUS hci_set_session_id(const uint8_t *session_id);

const uint8_t default_session_id[HCI_REGISTRY_SESSION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static tHCI_SESSION_INFO g_hci_session_info;
static tMUTEX g_hci_session_lock = MUTEX_INIT_VAL("hci_session");

/**
 * @brief 初始化hci session
 * @details 初始化本地hci session缓存，并判断NFCC内session状态，不存在session或者与本地缓存不一致时重新创建session
 * @return 本地无session缓存，但NFCC内session已经初始化时，返回NCI_STATUS_EXT_ALREADY_OPENED
 *         session已初始化并且本地与NFCC内session状态已经同步时返回NCI_STATUS_EXT_ALREADY_OPENED
 *         session初始化成功返回NCI_STATUS_OK
 */
tNCI_STATUS hci_session_init(void) {
    tNCI_STATUS status;
    tNFC_STATUS nfc_status;
    NFCLOG_D("enter");
    nfc_status = osi_mutex_init(&g_hci_session_lock);
    if (NFC_STATUS_OK != nfc_status) {
        NFCLOG_E("init mutex for hci session failed");
        return NCI_STATUS_EXT_FAILED;
    }
    uint8_t session_id[HCI_REGISTRY_SESSION_ID_LEN] = {0};
    status = hci_cmd_any_open_pipe(HCI_STATIC_PIPE_ADMIN);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("open admin pipe failed");
        goto exit;
    }

    // 从NFCC中获取session id并检查是否存在合法的session
    status = hci_get_session_id(session_id);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("get session id from NFCC failed");
        goto exit;
    }
    NFCLOG_D("session id:%02X%02X%02X%02X%02X%02X%02X%02X",
        session_id[0], session_id[1], session_id[2], session_id[3],
        session_id[4], session_id[5], session_id[6], session_id[7]);
    if (0 == memcmp(default_session_id, session_id, HCI_REGISTRY_SESSION_ID_LEN)) {
        // 不存在合法的session
        NFCLOG_D("no hci session found");
        goto reset_session;
    }
    // NFCC内有缓存
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        status = NCI_STATUS_EXT_GET_LOCK_FAILED;
        goto exit;
    }
    if ((0 == memcmp(default_session_id, g_hci_session_info.session_id, HCI_REGISTRY_SESSION_ID_LEN))) {
        // 本地有缓存
        if (0 == memcmp(g_hci_session_info.session_id, session_id, HCI_REGISTRY_SESSION_ID_LEN)) {
            // session id与NFCC内的一致
            NFCLOG_D("session id match");
            osi_mutex_unlock(&g_hci_session_lock);
            status = NCI_STATUS_EXT_ALREADY_OPENED;
            goto exit;
        }
        goto reset_session; // session id与缓存的不一致，必须重置session初始化
    } else {
        // 本地无缓存
        osi_mutex_unlock(&g_hci_session_lock);
        status = NCI_STATUS_EXT_ALREADY_OPENED;
        goto exit;
    }
    osi_mutex_unlock(&g_hci_session_lock);
reset_session:
    status = hci_cmd_adm_clear_all_pipe();
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("clear pipe failed");
        goto exit;
    }
    status = hci_cmd_any_open_pipe(HCI_STATIC_PIPE_ADMIN);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("open admin pipe failed");
        goto exit;
    }
    // TODO 使用随机数生成session id
    for (int i = 0; i < HCI_REGISTRY_SESSION_ID_LEN; ++i) {
        session_id[i] = i;
    }
    status = hci_set_session_id(session_id);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("set session failed. ret:%d", status);
        goto exit;
    }
    NFCLOG_D("hci session init done");
exit:
    return status;
}

/**
 * @brief 去初始化hci session
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS hci_session_deinit(void) {
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return NCI_STATUS_OK;
    }
    if (NFC_STATUS_OK != osi_mutex_unlock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
    }
    osi_mutex_deinit(&g_hci_session_lock);
    return NCI_STATUS_OK;
}

/**
 * @brief 从NFCC中获取session id
 * @param[out] session_id 用与存放获取到的session id，内存空间至少需要8-bytes
 * @return 成功是返回NCI_STATUS_OK
 */
static tNCI_STATUS hci_get_session_id(uint8_t *session_id) {
    tNCI_STATUS status;
    tHCI_PARAM *param = NULL;
    if (NULL == session_id) {
        NFCLOG_E("session id is NULL");
        status = NCI_STATUS_EXT_INVALID_PARAM;
        goto exit;
    }
    status = hci_cmd_any_get_param(HCI_STATIC_PIPE_ADMIN, HCI_REGISTRY_SESSION_ID, &param);
    if (NCI_STATUS_OK != status) {
        NFCLOG_W("get session id failed");
        goto exit;
    }
    // 检查是否是合法的session id格式
    if ((HCI_REGISTRY_SESSION_ID != param->index) || (HCI_REGISTRY_SESSION_ID_LEN != param->len)) {
        NFCLOG_W("invalid session id got. id:%02X len:%d", param->index, param->len);
        goto clean;
    }
    if (!osi_memcpy_s(session_id, HCI_REGISTRY_SESSION_ID_LEN, param->dat, HCI_REGISTRY_SESSION_ID_LEN)) {
        NFCLOG_W("copy session id failed");
        status = NCI_STATUS_EXT_COPY_FAILED;
        goto clean;
    }
clean:
    osi_free(param);
    param = NULL;
exit:
    if (NCI_STATUS_OK == status) {
        if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
            NFCLOG_W("hci session lock is released");
            return NCI_STATUS_EXT_GET_LOCK_FAILED;
        }
        if (!osi_memcpy_s(g_hci_session_info.session_id, HCI_REGISTRY_SESSION_ID_LEN, session_id, HCI_REGISTRY_SESSION_ID_LEN)) {
            NFCLOG_E("update session buffer failed");
        }
        osi_mutex_unlock(&g_hci_session_lock);
    }
    return status;
}

/**
 * @brief 设置session_id到NFCC中
 * @param session_id 要设置的session id，内容长度必须为8-bytes
 * @return
 */
static tNCI_STATUS hci_set_session_id(const uint8_t *session_id) {
    tNCI_STATUS status;
    tHCI_PARAM *param = NULL;
    param = osi_malloc(sizeof(tHCI_PARAM) + HCI_REGISTRY_SESSION_ID_LEN);
    if (NULL == param) {
        NFCLOG_E("malloc failed");
        status = NCI_STATUS_EXT_ALLOC_FAILED;
        goto exit;
    }
    param->index = HCI_REGISTRY_SESSION_ID;
    param->len = HCI_REGISTRY_SESSION_ID_LEN;
    if (!osi_memcpy_s(param->dat, HCI_REGISTRY_SESSION_ID_LEN, session_id, HCI_REGISTRY_SESSION_ID_LEN)) {
        NFCLOG_E("memcpy failed");
        status = NCI_STATUS_EXT_COPY_FAILED;
        goto clean;
    }
    status = hci_cmd_any_set_param(HCI_STATIC_PIPE_ADMIN, param);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("set param failed");
    }

clean:
    osi_free(param);
    param = NULL;
exit:
    if (NCI_STATUS_OK == status) {
        if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
            NFCLOG_W("hci session lock is released");
            return NCI_STATUS_EXT_GET_LOCK_FAILED;
        }
        if (!osi_memcpy_s(g_hci_session_info.session_id, HCI_REGISTRY_SESSION_ID_LEN, session_id, HCI_REGISTRY_SESSION_ID_LEN)) {
            NFCLOG_E("update session buffer failed");
        }
        osi_mutex_unlock(&g_hci_session_lock);
    }
    return status;
}

/**
 * @brief 设置white list参数
 * @note 把white list设置成所有已知的EE
 * @param ee_infos 当前EE状态，通过ee_get_info接口从EE模块中获取
 * @param ee_nums  已知的EE数量
 * @return 成功时返回NCI_STATUS_OK
 */
static tNCI_STATUS hci_session_set_host_white_list(const tNCI_EE_INFO *ee_infos, uint8_t ee_nums) {
    tNCI_STATUS status;
    tHCI_PARAM *param = NULL;
    uint8_t host_num = 0;
    param = osi_malloc(sizeof(tHCI_PARAM) + MAX_HOST_NUM);
    if (NULL == param) {
        NFCLOG_E("malloc failed");
        status = NCI_STATUS_EXT_ALLOC_FAILED;
        goto exit;
    }
    param->index = HCI_REGISTRY_WHITELIST;
    for (int i = 0; i < ee_nums; ++i) {
        if (ee_infos[i].using_hci) {
            param->dat[host_num++] = ee_infos[i].ee_id;
        }
    }
    param->len = host_num;
    status = hci_cmd_any_set_param(HCI_STATIC_PIPE_ADMIN, param);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("set param failed");
    }
    osi_free(param);
    param = NULL;
exit:
    return status;
}

/**
 * @brief 清空hci session缓存
 * @note 包含session id和pipe缓存
 */
void hci_reset_session_info(void) {
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return;
    }
    if (!osi_memset_s(&g_hci_session_info, sizeof(tHCI_SESSION_INFO), 0, sizeof(tHCI_SESSION_INFO))) {
        NFCLOG_W("reset hci session info failed");
    }
    if (!osi_memcpy_s(g_hci_session_info.session_id, sizeof(g_hci_session_info.session_id), default_session_id, sizeof(default_session_id))) {
        NFCLOG_W("reset session id failed");
    }
    osi_mutex_unlock(&g_hci_session_lock);
    // TODO 考虑是否需要也通知到NFCC
}

/**
 * @brief 创建并打开pipe
 * @param[in] src_gate  pipe对应的本地gate
 * @param[in] dest_host pipe对应的远端host
 * @param[in] dest_gate pipe对应的远端gate
 * @param[in/out] pipe  pipe id，指定为0时，执行创建流程，并由NFCC分配；指定为具体值时，直接尝试open pipe
 * @return 成功时返回NCI_STATUS_OK
 */
static tNCI_STATUS hci_create_and_open_pipe(uint8_t src_gate, uint8_t dest_host, uint8_t dest_gate, uint8_t *pipe) {
    tNCI_STATUS status;

    if (NULL == pipe) {
        NFCLOG_E("pipe is NULL");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }

    if (*pipe) {
        // 如果是已知的pipe，先把pipe加到缓存中，再尝试open pipe
        hci_session_add_pipe(*pipe, src_gate, dest_host, dest_gate, false);
        status = hci_cmd_any_open_pipe(*pipe);
        if (NCI_STATUS_OK == status) {
            return NCI_STATUS_OK;
        }
        *pipe = 0;
    }

    // 如果没有指定pipe id，或者pipe打开失败（pipe不存在），则先创建pipe
    if (!*pipe) {
        status = hci_cmd_adm_create_pipe(src_gate, dest_host, dest_gate, pipe);
        if (NCI_STATUS_OK != status) {
            NFCLOG_W("create pipe:%02X failed, ret:%d. src_gate:%02X dest_host:%02X dest_gate:%02X", status, *pipe,
                src_gate, dest_host, dest_gate);
            return status;
        }
    }

    if (!*pipe) {
        NFCLOG_E("invalid pipe id got");
        return NCI_STATUS_EXT_FAILED;
    }
    status = hci_cmd_any_open_pipe(*pipe);
    return status;
}

/**
 * @brief 初始化所有已知hci pipe
 * @note 此方法会初始化所有支持HCI的EE，并且创建每个EE已知的需要用到的pipe
 * @param is_new_session 是否是新创建的session
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS hci_init_all_pipe(bool is_new_session) {
    const tHCI_PIPE_INFO known_conn_pipes[] = {
        {.pipe_id = HCI_DYNAMIC_PIPE_ESE_CONNECTIVITY, .local_gate = HCI_GATE_CONNECTIVITY, .dest_host = HCI_HOST_ID_ESE, .dest_gate = HCI_GATE_CONNECTIVITY},
        {.pipe_id = HCI_DYNAMIC_PIPE_SIM1_CONNECTIVITY, .local_gate = HCI_GATE_CONNECTIVITY, .dest_host = HCI_HOST_ID_SIM1, .dest_gate = HCI_GATE_CONNECTIVITY},
        {.pipe_id = HCI_DYNAMIC_PIPE_SIM2_CONNECTIVITY, .local_gate = HCI_GATE_CONNECTIVITY, .dest_host = HCI_HOST_ID_SIM2, .dest_gate = HCI_GATE_CONNECTIVITY},
    };
    const uint8_t total_konwn_conn_pipes = sizeof(known_conn_pipes) / sizeof(tHCI_PIPE_INFO);
    const tHCI_PIPE_INFO known_pipes[] = {
        {.pipe_id = HCI_DYNAMIC_PIPE_APDU, .local_gate = HCI_GATE_APP_APDU, .dest_host = HCI_HOST_ID_ESE, .dest_gate = HCI_GATE_APDU},
    };
    const uint8_t total_konwn_pipes = sizeof(known_pipes) / sizeof(tHCI_PIPE_INFO);
    tNCI_STATUS status;
    uint8_t total_ee = NCI_MAX_NFCEE_SUPPORT;
    tNCI_EE_INFO ee_infos[NCI_MAX_NFCEE_SUPPORT];
    NFCLOG_D("enter");
    if (!is_new_session) {
        // 如果是已经存在的session，默认所有pipe存在
        for (int i = 0; i < total_konwn_conn_pipes; ++i) {
            hci_session_add_pipe(known_conn_pipes[i].pipe_id, known_conn_pipes[i].local_gate, known_conn_pipes[i].dest_host, known_conn_pipes[i].dest_gate, true);
        }
        for (int i = 0; i < total_konwn_pipes; ++i) {
            hci_session_add_pipe(known_pipes[i].pipe_id, known_pipes[i].local_gate, known_pipes[i].dest_host, known_pipes[i].dest_gate, true);
        }
    }
    status = ee_get_info(&total_ee, ee_infos);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("get ee infos failed");
        goto exit;
    }
    NFCLOG_D("got ee infos. cnt:%d", total_ee);
    status = hci_session_set_host_white_list(ee_infos, total_ee);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("set host white list failed");
        goto exit;
    }
    for (uint8_t i = 0; i < total_ee; ++i) {
        if (!ee_infos[i].using_hci) {
            NFCLOG_D("skip ee:%02X not support hci", ee_infos[i].ee_id);
            continue;
        }
        // 使能所有支持HCI的EE
        NFCLOG_D("handle ee:%02X", ee_infos[i].ee_id);
        status = ee_mode_set(ee_infos[i].ee_id, NCI_NFCEE_MODE_ENABLE);
        if (NCI_STATUS_OK != status) {
            NFCLOG_W("ee:%02X enable failed, skip init hci pipe on this ee", ee_infos[i].ee_id);
            hci_session_clear_pipes_on_ee(ee_infos[i].ee_id);
            status = NCI_STATUS_OK; // enable EE失败也标记操作完成
            continue;
        }
        // 等待EE enable后，检查所有需要的pipe的状态
        for (uint8_t j = 0; j < total_konwn_pipes; ++j) {
            if (ee_infos[i].ee_id != known_pipes[j].dest_host) {
                continue;
            }
            uint8_t pipe = known_pipes[j].pipe_id;
            // 先设置pipe的状态为closed，如果pipe不存在（EE全量初始化会clear all pipe，会清空缓存），则直接走创建流程
            // 如果pipe没有被清掉，先假设pipe存在，尝试open
            // 如果是新建的session，pipe也是不存在的，直接走创建流程
            if ((NCI_STATUS_EXT_REJECTED == hci_session_update_pipe_status(pipe, false)) || is_new_session) {
                pipe = 0;
            }
            status = hci_create_and_open_pipe(known_pipes[j].local_gate, known_pipes[j].dest_host, known_pipes[j].dest_gate, &pipe);
            if (NCI_STATUS_OK != status) {
                NFCLOG_W("create pipe:%02X failed, ret:%d. src_gate:%02X dest_host:%02X dest_gate:%02X", status, pipe,
                    known_pipes[j].local_gate, known_pipes[j].dest_host, known_pipes[j].dest_gate);
                continue;
            }
            if (known_pipes[j].pipe_id != pipe) {
                NFCLOG_W("warnning: dyn_pipe is diff from db. pipe_from_nfcc:%02X pipe_from_db:%02X", pipe, known_pipes[j].pipe_id);
                // 如果NFCC分配到的动态pipe id与预期的不一致，优先用NFCC分配的，再与FW确认分配逻辑
            }
        }
    }
exit:
    return status;
}

/**
 * @brief 清空hci session缓存中的所有pipe信息
 * @note 这个操作应该发生在主端主动clear all pipes/FW升级后
 */
void hci_session_clear_all_pipes(void) {
    NFCLOG_D("%s", __func__);
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return;
    }
    if (!osi_memset_s(g_hci_session_info.dyn_pipes, sizeof(g_hci_session_info.dyn_pipes), 0, sizeof(g_hci_session_info))) {
        NFCLOG_W("%s memset failed", __func__);
    }
    osi_mutex_unlock(&g_hci_session_lock);
}

void hci_session_clear_pipes_on_ee(uint8_t host_id) {
    NFCLOG_D("%s host_id:%02X", __func__, host_id);
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return;
    }
    for (int i = 0; i < MAX_DYN_PIPE; ++i) {
        if (host_id == g_hci_session_info.dyn_pipes[i].dest_host) {
            NFCLOG_D("clear pipe:%02X", g_hci_session_info.dyn_pipes[i].pipe_id);
            if (!osi_memset_s(&g_hci_session_info.dyn_pipes[i], sizeof(tHCI_PIPE_INFO), 0, sizeof(tHCI_PIPE_INFO))) {
                NFCLOG_W("%s clear pipe failed", __func__);
            }
        }
    }
    osi_mutex_unlock(&g_hci_session_lock);
}

/**
 * @brief 添加新的pipe到hci session缓存中
 * @param pipe_id    新增pipe的id
 * @param local_gate 新增pipe使用的本地gate
 * @param dest_host  新增pipe对应的远端host
 * @param dest_gate  新增pipe对应的远端gate
 * @param is_opened  新增pipe的open状态
 * @return
 */
tNCI_STATUS hci_session_add_pipe(uint8_t pipe_id, uint8_t local_gate, uint8_t dest_host, uint8_t dest_gate, bool is_opened) {
    tNCI_STATUS status = NCI_STATUS_OK;
    int i;
    if (pipe_id < HCI_DYNAMIC_PIPE_START) {
        // static pipe不作记录
        return status;
    }
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    // 先检查pipe是否已经存在
    for (i = 0; i < MAX_DYN_PIPE; ++i) {
        if (pipe_id == g_hci_session_info.dyn_pipes[i].pipe_id) {
            NFCLOG_D("pipe already create");
            // 更新open状态
            g_hci_session_info.dyn_pipes[i].is_opened = is_opened;
            status = NCI_STATUS_EXT_ALREADY_OPENED;
            goto exit;
        }
    }
    // 寻找空闲的pipe缓存位置
    for (i = 0; i < MAX_DYN_PIPE; ++i) {
        if (0 == g_hci_session_info.dyn_pipes[i].pipe_id) {
            break;
        }
    }
    if (MAX_DYN_PIPE == i) {
        NFCLOG_W("pipe pool overflow");
        status = NCI_STATUS_EXT_REJECTED;
        goto exit;
    }
    // 把pipe信息记录到缓存里面
    g_hci_session_info.dyn_pipes[i].pipe_id = pipe_id;
    g_hci_session_info.dyn_pipes[i].local_gate = local_gate;
    g_hci_session_info.dyn_pipes[i].dest_host = dest_host;
    g_hci_session_info.dyn_pipes[i].dest_gate = dest_gate;
    g_hci_session_info.dyn_pipes[i].is_opened = is_opened;
    NFCLOG_D("%s add pipe:%02X local_gate:%02X dest_host:%02X dest_gate:%02X is_opened:%d", __func__,
             pipe_id, local_gate, dest_host, dest_gate, is_opened);
exit:
    osi_mutex_unlock(&g_hci_session_lock);
    return status;
}

/**
 * @brief 更新hci session缓存中pipe的open状态
 * @param pipe_id 要更新的pipe
 * @param is_opened 新的pipe open状态
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS hci_session_update_pipe_status(uint8_t pipe_id, bool is_opened) {
    tNCI_STATUS status = NCI_STATUS_OK;
    int i;
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    // 寻找pipe在缓存中对应的index
    for (i = 0; i < MAX_DYN_PIPE; ++i) {
        if (pipe_id == g_hci_session_info.dyn_pipes[i].pipe_id) {
            break;
        }
    }
    if (i == MAX_DYN_PIPE) {
        NFCLOG_E("pipe not found");
        status = NCI_STATUS_EXT_REJECTED;
        goto exit;
    }
    g_hci_session_info.dyn_pipes[i].is_opened = is_opened;
    NFCLOG_D("%s update pipe:%02X status to %d", __func__, pipe_id, is_opened);
exit:
    osi_mutex_unlock(&g_hci_session_lock);
    return status;
}

/**
 * @brief 从hci session中删除指定pipe的缓存
 * @param pipe_id 要删除的pipe
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS hci_session_delete_pipe(uint8_t pipe_id) {
    tNCI_STATUS status = NCI_STATUS_OK;
    int i;
    NFCLOG_D("%s pipe_id:%02X", __func__, pipe_id);
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    // 寻找pipe在缓存中对应的index
    for (i = 0; i < MAX_DYN_PIPE; ++i) {
        if (pipe_id == g_hci_session_info.dyn_pipes[i].pipe_id) {
            if (!osi_memset_s(&g_hci_session_info.dyn_pipes[i], sizeof(tHCI_PIPE_INFO), 0, sizeof(tHCI_PIPE_INFO))) {
                NFCLOG_E("%s memset failed", __func__);
                status = NCI_STATUS_EXT_COPY_FAILED;
            }
            goto exit;
        }
    }
    NFCLOG_W("pipe not found");
exit:
    osi_mutex_unlock(&g_hci_session_lock);
    return status;
}

/**
 * @brief 把hci session中缓存的数据都dump出来
 */
void hci_session_dump(void) {
    int i, total_pipe = 0;
    if (NFC_STATUS_OK != osi_mutex_lock(&g_hci_session_lock)) {
        NFCLOG_W("hci session lock is released");
        return;
    }
    NFCLOG_D("%s session id:%02X%02X%02X%02X%02X%02X%02X%02X", __func__, g_hci_session_info.session_id[0], g_hci_session_info.session_id[1],
            g_hci_session_info.session_id[2], g_hci_session_info.session_id[3], g_hci_session_info.session_id[4], g_hci_session_info.session_id[5],
            g_hci_session_info.session_id[6], g_hci_session_info.session_id[7]);
    for (i = 0; i < MAX_DYN_PIPE; ++i) {
        if (0 != g_hci_session_info.dyn_pipes[i].pipe_id) {
            NFCLOG_D("%s index:%d pipe id:%02X local gate:%02X dest host:%02X dest gate:%02X is opened:%d", __func__, i,
                     g_hci_session_info.dyn_pipes[i].pipe_id, g_hci_session_info.dyn_pipes[i].local_gate,
                     g_hci_session_info.dyn_pipes[i].dest_host, g_hci_session_info.dyn_pipes[i].dest_gate,
                     g_hci_session_info.dyn_pipes[i].is_opened);
            total_pipe++;
        }
    }
    osi_mutex_unlock(&g_hci_session_lock);
    NFCLOG_D("%s total pipe:%d", __func__, total_pipe);
}

#endif // IS_FEATURE_ON(NCI_FEATURE_HCI)
